﻿// Decompiled with JetBrains decompiler
// Type: UnityEngine.Playables.ScriptPlayable`1
// Assembly: UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: E6AE6B5A-2752-4B07-9528-C8B77C62CE79
// Assembly location: C:\Users\windys\Unity\2021.3.39f1c1\Editor\Data\Managed\UnityEngine\UnityEngine.CoreModule.dll
// XML documentation location: C:\Users\windys\Unity\2021.3.39f1c1\Editor\Data\Managed\UnityEngine\UnityEngine.CoreModule.xml

using System;

#nullable disable
namespace UnityEngine.Playables
{
  /// <summary>
  ///   <para>A IPlayable implementation that contains a PlayableBehaviour for the PlayableGraph. PlayableBehaviour can be used to write custom Playable that implement their own PrepareFrame callback.</para>
  /// </summary>
  public struct ScriptPlayable<T> : IPlayable, IEquatable<ScriptPlayable<T>> where T : class, IPlayableBehaviour, new()
  {
    private PlayableHandle m_Handle;
    private static readonly ScriptPlayable<T> m_NullPlayable = new ScriptPlayable<T>(PlayableHandle.Null);

    public static ScriptPlayable<T> Null => ScriptPlayable<T>.m_NullPlayable;

    public static ScriptPlayable<T> Create(PlayableGraph graph, int inputCount = 0)
    {
      return new ScriptPlayable<T>(ScriptPlayable<T>.CreateHandle(graph, default (T), inputCount));
    }

    public static ScriptPlayable<T> Create(PlayableGraph graph, T template, int inputCount = 0)
    {
      return new ScriptPlayable<T>(ScriptPlayable<T>.CreateHandle(graph, template, inputCount));
    }

    private static PlayableHandle CreateHandle(PlayableGraph graph, T template, int inputCount)
    {
      object scriptInstance = (object) template != null ? ScriptPlayable<T>.CloneScriptInstance((IPlayableBehaviour) template) : ScriptPlayable<T>.CreateScriptInstance();
      if (scriptInstance == null)
      {
        Debug.LogError((object) ("Could not create a ScriptPlayable of Type " + typeof (T)?.ToString()));
        return PlayableHandle.Null;
      }
      PlayableHandle playableHandle = graph.CreatePlayableHandle();
      if (!playableHandle.IsValid())
        return PlayableHandle.Null;
      playableHandle.SetInputCount(inputCount);
      playableHandle.SetScriptInstance(scriptInstance);
      return playableHandle;
    }

    private static object CreateScriptInstance()
    {
      return !typeof (ScriptableObject).IsAssignableFrom(typeof (T)) ? (object) new T() : (object) (ScriptableObject.CreateInstance(typeof (T)) as T);
    }

    private static object CloneScriptInstance(IPlayableBehaviour source)
    {
      UnityEngine.Object source1 = source as UnityEngine.Object;
      if (source1 != (UnityEngine.Object) null)
        return ScriptPlayable<T>.CloneScriptInstanceFromEngineObject(source1);
      return source is ICloneable source2 ? ScriptPlayable<T>.CloneScriptInstanceFromIClonable(source2) : (object) null;
    }

    private static object CloneScriptInstanceFromEngineObject(UnityEngine.Object source)
    {
      UnityEngine.Object @object = UnityEngine.Object.Instantiate(source);
      if (@object != (UnityEngine.Object) null)
        @object.hideFlags |= HideFlags.DontSave;
      return (object) @object;
    }

    private static object CloneScriptInstanceFromIClonable(ICloneable source) => source.Clone();

    internal ScriptPlayable(PlayableHandle handle)
    {
      this.m_Handle = !handle.IsValid() || typeof (T).IsAssignableFrom(handle.GetPlayableType()) ? handle : throw new InvalidCastException(string.Format("Incompatible handle: Trying to assign a playable data of type `{0}` that is not compatible with the PlayableBehaviour of type `{1}`.", (object) handle.GetPlayableType(), (object) typeof (T)));
    }

    public PlayableHandle GetHandle() => this.m_Handle;

    public T GetBehaviour() => this.m_Handle.GetObject<T>();

    public static implicit operator Playable(ScriptPlayable<T> playable)
    {
      return new Playable(playable.GetHandle());
    }

    public static explicit operator ScriptPlayable<T>(Playable playable)
    {
      return new ScriptPlayable<T>(playable.GetHandle());
    }

    public bool Equals(ScriptPlayable<T> other) => this.GetHandle() == other.GetHandle();
  }
}
